package me.helllp.bootman.common.services;

import java.util.Date;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;

/**
 * redis的工具服务类
 * 
 * @author 虎头
 *
 */
@ConditionalOnBean(RedisTemplate.class)
public class RedisTemplateService {
	@Autowired
	private RedisTemplate<String, Object> redisTemplate;

	/**
	 * 批量删除对应的value
	 * 
	 * @param keys
	 */
	public void remove(final String... keys) {
		for (String key : keys) {
			remove(key);
		}
	}

	/**
	 * 批量删除key
	 * 
	 * @param pattern
	 */
	public void removePattern(final String pattern) {
		
		Set<String> keys = redisTemplate.keys(pattern);
		if (keys.size() > 0)
			redisTemplate.delete(keys);
	}

	/**
	 * 删除对应的value
	 * 
	 * @param key
	 */
	public void remove(final String key) {
		if (exists(key)) {
			redisTemplate.delete(key);
		}
	}

	/**
	 * 判断缓存中是否有对应的value
	 * 
	 * @param key
	 * @return
	 */
	public boolean exists(final String key) {
		return redisTemplate.hasKey(key);
	}

	/**
	 * 读取缓存
	 * 
	 * @param key
	 * @return
	 */
	public Object get(final String key) {
		Object result = null;
		ValueOperations<String, Object> operations = redisTemplate.opsForValue();
		result = operations.get(key);
		return result;
	}

	/**
	 * 写入缓存
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean set(final String key, Object value) {
		boolean result = false;
		try {
			ValueOperations<String, Object> operations = redisTemplate.opsForValue();
			operations.set(key, value);
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 写入缓存
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean set(final String key, Object value, Long expireTime) {
		boolean result = false;
		try {
			ValueOperations<String, Object> operations = redisTemplate.opsForValue();
			operations.set(key, value);
			redisTemplate.expire(key, expireTime, TimeUnit.MILLISECONDS);
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 访问控制
	 * @param key		指定redis key
	 * @param count		指定访问的次数
	 * @param times		指定时间周期(以秒为单位)
	 * @return
	 */
	public boolean ifAllowed(String key, long count, long times) {
		boolean flag = true;

		ValueOperations<String, Object> operations = redisTemplate.opsForValue();
		
		if (exists(key)) {
			// key对应的value自加1
			Long l = operations.increment(key, 1L);

			try {
				// 访问次数超过规定，则不允许访问
				if (l > count) {
					flag = false;
				}
			} catch (RuntimeException e) {
				e.printStackTrace();
			}
		} else {
			// 第一次访问，设置初始值1
			set(key, 1, times);
		}

		return flag;
	}

	public void increment(String key){
		ValueOperations<String, Object> operations = redisTemplate.opsForValue();

		if (exists(key)) {
			// key对应的value自加1
			operations.increment(key, 1L);
		} else {
			// 第一次访问，设置初始值1
			set(key, 1L);
		}		
	}
	
	public void reduce(String key){
		ValueOperations<String, Object> operations = redisTemplate.opsForValue();
		if (exists(key)) {
			// key对应的value自加1
			operations.increment(key, -1L);
		} 	
	}
	
    /**
     * 获取缓存set数据
     * 
     * @param k
     * @return
     */
    public Set<Object> getSet(String k) {
        SetOperations<String, Object> setOps = redisTemplate.opsForSet();
        return setOps.members(k);
    }

    /**
     * 进行set类型的缓存
     * 
     * @param k
     * @param v
     * @return
     */
    public boolean cacheSet(String k, Set<Object> v) {
    	SetOperations<String, Object> setOps = redisTemplate.opsForSet();
        setOps.add(k, v.toArray(new Object[v.size()]));
        return true;
    }  
    
    public boolean cacheSet(String k, Long v){
    	SetOperations<String, Object> setOps = redisTemplate.opsForSet();
        setOps.add(k, v);
        return true;
    }
    
    /**
     * 设置缓存失效的时间
     * 
     * @param k
     * @param d
     * @return
     */
    public boolean expireDate(String k, Date d){
    	return redisTemplate.expireAt(k, d);
    }
    
    /**
     * 指定时间类型---秒
     * @param key
     * @return
     */
    public long getExpireTimeType(String key){
        long time = redisTemplate.getExpire(key,TimeUnit.SECONDS);
        return time;
    }
}

